home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 4 / The 640 Meg Shareware Studio CD-ROM Volume IV (Data Express)(1994).ISO / clang / rzsz0593.zip / ZM.C < prev    next >
C/C++ Source or Header  |  1993-05-03  |  18KB  |  909 lines

  1. /*
  2.  *   Z M . C
  3.  *    Copyright 1991 Omen Technology Inc All Rights Reserved
  4.  *    ZMODEM protocol primitives
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr, eflag) receive header - binary or hex
  10.  *    zsdata(buf, len, frameend) send data
  11.  *    zrdata(buf, len) receive data
  12.  *    stohdr(pos) store position data in Txhdr
  13.  *    unsigned long rclhdr(hdr) recover position offset from header
  14.  * 
  15.  *
  16.  *    This version implements numerous enhancements including ZMODEM
  17.  *    Run Length Encoding and variable length headers.  These
  18.  *    features were not funded by the original Telenet development
  19.  *    contract.
  20.  * 
  21.  *  This software may be freely used for educational (didactic
  22.  *  only) purposes.  This software may also be freely used to
  23.  *  support file transfer operations to or from licensed Omen
  24.  *  Technology products.  Use with other commercial or shareware
  25.  *  programs (Crosstalk, Procomm, etc.) REQUIRES REGISTRATION.
  26.  *
  27.  *  Any programs which use part or all of this software must be
  28.  *  provided in source form with this notice intact except by
  29.  *  written permission from Omen Technology Incorporated.
  30.  * 
  31.  * Use of this software for commercial or administrative purposes
  32.  * except when exclusively limited to interfacing Omen Technology
  33.  * products requires a per port license payment of $20.00 US per
  34.  * port (less in quantity).  Use of this code by inclusion,
  35.  * decompilation, reverse engineering or any other means
  36.  * constitutes agreement to these conditions and acceptance of
  37.  * liability to license the materials and payment of reasonable
  38.  * legal costs necessary to enforce this license agreement.
  39.  *
  40.  *
  41.  *        Omen Technology Inc
  42.  *        Post Office Box 4681
  43.  *        Portland OR 97208
  44.  *
  45.  *    This code is made available in the hope it will be useful,
  46.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  47.  *    DAMAGES OF ANY KIND.
  48.  *
  49.  */
  50.  
  51. #ifndef CANFDX
  52. #include "zmodem.h"
  53. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  54. #endif
  55.  
  56. /* Globals used by ZMODEM functions */
  57. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame */
  58. int Rxtype;        /* Type of header received */
  59. int Rxhlen;        /* Length of header received */
  60. int Rxcount;        /* Count of data bytes received */
  61. char Rxhdr[ZMAXHLEN];    /* Received header */
  62. char Txhdr[ZMAXHLEN];    /* Transmitted header */
  63. unsigned long Rxpos;        /* Received file position */
  64. unsigned long Txpos;        /* Transmitted file position */
  65. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  66. int Crc32t;        /* Controls 32 bit CRC being sent */
  67.             /* 1 == CRC32,  2 == CRC32 + RLE */
  68. int Crc32r;        /* Indicates/controls 32 bit CRC being received */
  69.             /* 0 == CRC16,  1 == CRC32,  2 == CRC32 + RLE */
  70. int Usevhdrs;        /* Use variable length headers */
  71. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  72. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  73. char *Altcan;        /* Alternate canit string */
  74.  
  75. static lastsent;    /* Last char we sent */
  76. static Not8bit;        /* Seven bits seen on header */
  77.  
  78. static char *frametypes[] = {
  79.     "No Response to Error Correction Request",    /* -4 */
  80.     "No Carrier Detect",        /* -3 */
  81.     "TIMEOUT",        /* -2 */
  82.     "ERROR",        /* -1 */
  83. #define FTOFFSET 4
  84.     "ZRQINIT",
  85.     "ZRINIT",
  86.     "ZSINIT",
  87.     "ZACK",
  88.     "ZFILE",
  89.     "ZSKIP",
  90.     "ZNAK",
  91.     "ZABORT",
  92.     "ZFIN",
  93.     "ZRPOS",
  94.     "ZDATA",
  95.     "ZEOF",
  96.     "ZFERR",
  97.     "ZCRC",
  98.     "ZCHALLENGE",
  99.     "ZCOMPL",
  100.     "ZCAN",
  101.     "ZFREECNT",
  102.     "ZCOMMAND",
  103.     "ZSTDERR",
  104.     "xxxxx"
  105. #define FRTYPES 22    /* Total number of frame types in this array */
  106.             /*  not including psuedo negative entries */
  107. };
  108.  
  109. static char badcrc[] = "Bad CRC";
  110.  
  111. /* Send ZMODEM binary header hdr of type type */
  112. zsbhdr(len, type, hdr)
  113. register char *hdr;
  114. {
  115.     register int n;
  116.     register unsigned short crc;
  117.  
  118. #ifndef DSZ
  119.     vfile("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  120.       frametypes[type+FTOFFSET], rclhdr(hdr));
  121. #endif
  122.     if (type == ZDATA)
  123.         for (n = Znulls; --n >=0; )
  124.             xsendline(0);
  125.  
  126.     xsendline(ZPAD); xsendline(ZDLE);
  127.  
  128.     switch (Crc32t=Txfcs32) {
  129.     case 2:
  130.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  131.         flushmo();  break;
  132.     case 1:
  133.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  134.     default:
  135.         if (Usevhdrs) {
  136.             xsendline(ZVBIN);
  137.             zsendline(len);
  138.         }
  139.         else
  140.             xsendline(ZBIN);
  141.         zsendline(type);
  142.         crc = updcrc(type, 0);
  143.  
  144.         for (n=len; --n >= 0; ++hdr) {
  145.             zsendline(*hdr);
  146.             crc = updcrc((0377& *hdr), crc);
  147.         }
  148.         crc = updcrc(0,updcrc(0,crc));
  149.         zsendline(crc>>8);
  150.         zsendline(crc);
  151.     }
  152.     if (type != ZDATA)
  153.         flushmo();
  154. }
  155.  
  156.  
  157. /* Send ZMODEM binary header hdr of type type */
  158. zsbh32(len, hdr, type, flavour)
  159. register char *hdr;
  160. {
  161.     register int n;
  162.     register unsigned long crc;
  163.  
  164.     xsendline(flavour); 
  165.     if (Usevhdrs) 
  166.         zsendline(len);
  167.     zsendline(type);
  168.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  169.  
  170.     for (n=len; --n >= 0; ++hdr) {
  171.         crc = UPDC32((0377 & *hdr), crc);
  172.         zsendline(*hdr);
  173.     }
  174.     crc = ~crc;
  175.     for (n=4; --n >= 0;) {
  176.         zsendline((int)crc);
  177.         crc >>= 8;
  178.     }
  179. }
  180.  
  181. /* Send ZMODEM HEX header hdr of type type */
  182. zshhdr(len, type, hdr)
  183. register char *hdr;
  184. {
  185.     register int n;
  186.     register unsigned short crc;
  187.  
  188. #ifndef DSZ
  189.     vfile("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  190.       frametypes[type+FTOFFSET], rclhdr(hdr));
  191. #endif
  192.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
  193.     if (Usevhdrs) {
  194.         sendline(ZVHEX);
  195.         zputhex(len);
  196.     }
  197.     else
  198.         sendline(ZHEX);
  199.     zputhex(type);
  200.     Crc32t = 0;
  201.  
  202.     crc = updcrc(type, 0);
  203.     for (n=len; --n >= 0; ++hdr) {
  204.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  205.     }
  206.     crc = updcrc(0,updcrc(0,crc));
  207.     zputhex(crc>>8); zputhex(crc);
  208.  
  209.     /* Make it printable on remote machine */
  210.     sendline(015); sendline(0212);
  211.     /*
  212.      * Uncork the remote in case a fake XOFF has stopped data flow
  213.      */
  214.     if (type != ZFIN && type != ZACK)
  215.         sendline(021);
  216.     flushmo();
  217. }
  218.  
  219. /*
  220.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  221.  */
  222. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  223. zsdata(buf, length, frameend)
  224. register char *buf;
  225. {
  226.     register unsigned short crc;
  227.  
  228. #ifndef DSZ
  229.     vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  230. #endif
  231.     switch (Crc32t) {
  232.     case 1:
  233.         zsda32(buf, length, frameend);  break;
  234.     case 2:
  235.         zsdar32(buf, length, frameend);  break;
  236.     default:
  237.         crc = 0;
  238.         for (;--length >= 0; ++buf) {
  239.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  240.         }
  241.         xsendline(ZDLE); xsendline(frameend);
  242.         crc = updcrc(frameend, crc);
  243.  
  244.         crc = updcrc(0,updcrc(0,crc));
  245.         zsendline(crc>>8); zsendline(crc);
  246.     }
  247.     if (frameend == ZCRCW)
  248.         xsendline(XON);
  249.     if (frameend != ZCRCG)
  250.         flushmo();
  251. }
  252.  
  253. zsda32(buf, length, frameend)
  254. register char *buf;
  255. {
  256.     register int c;
  257.     register unsigned long crc;
  258.  
  259.     crc = 0xFFFFFFFFL;
  260.     for (;--length >= 0; ++buf) {
  261.         c = *buf & 0377;
  262.         if (c & 0140)
  263.             xsendline(lastsent = c);
  264.         else
  265.             zsendline(c);
  266.         crc = UPDC32(c, crc);
  267.     }
  268.     xsendline(ZDLE); xsendline(frameend);
  269.     crc = UPDC32(frameend, crc);
  270.  
  271.     crc = ~crc;
  272.     for (c=4; --c >= 0;) {
  273.         zsendline((int)crc);  crc >>= 8;
  274.     }
  275. }
  276.  
  277. /*
  278.  * Receive array buf of max length with ending ZDLE sequence
  279.  *  and CRC.  Returns the ending character or error code.
  280.  *  NB: On errors may store length+1 bytes!
  281.  */
  282. zrdata(buf, length)
  283. register char *buf;
  284. {
  285.     register int c;
  286.     register unsigned short crc;
  287.     register char *end;
  288.     register int d;
  289.  
  290.     switch (Crc32r) {
  291.     case 1:
  292.         return zrdat32(buf, length);
  293.     case 2:
  294.         return zrdatr32(buf, length);
  295.     }
  296.  
  297.     crc = Rxcount = 0;  end = buf + length;
  298.     while (buf <= end) {
  299.         if ((c = zdlread()) & ~0377) {
  300. crcfoo:
  301.             switch (c) {
  302.             case GOTCRCE:
  303.             case GOTCRCG:
  304.             case GOTCRCQ:
  305.             case GOTCRCW:
  306.                 crc = updcrc((d=c)&0377, crc);
  307.                 if ((c = zdlread()) & ~0377)
  308.                     goto crcfoo;
  309.                 crc = updcrc(c, crc);
  310.                 if ((c = zdlread()) & ~0377)
  311.                     goto crcfoo;
  312.                 crc = updcrc(c, crc);
  313.                 if (crc & 0xFFFF) {
  314.                     zperr(badcrc);
  315.                     return ERROR;
  316.                 }
  317.                 Rxcount = length - (end - buf);
  318. #ifndef DSZ
  319.                 vfile("zrdata: %d  %s", Rxcount,
  320.                  Zendnames[d-GOTCRCE&3]);
  321. #endif
  322.                 return d;
  323.             case GOTCAN:
  324.                 zperr("Sender Canceled");
  325.                 return ZCAN;
  326.             case TIMEOUT:
  327.                 zperr("TIMEOUT");
  328.                 return c;
  329.             default:
  330.                 garbitch(); return c;
  331.             }
  332.         }
  333.         *buf++ = c;
  334.         crc = updcrc(c, crc);
  335.     }
  336. #ifdef DSZ
  337.     garbitch(); 
  338. #else
  339.     zperr("Data subpacket too long");
  340. #endif
  341.     return ERROR;
  342. }
  343.  
  344. zrdat32(buf, length)
  345. register char *buf;
  346. {
  347.     register int c;
  348.     register unsigned long crc;
  349.     register char *end;
  350.     register int d;
  351.  
  352.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  353.     while (buf <= end) {
  354.         if ((c = zdlread()) & ~0377) {
  355. crcfoo:
  356.             switch (c) {
  357.             case GOTCRCE:
  358.             case GOTCRCG:
  359.             case GOTCRCQ:
  360.             case GOTCRCW:
  361.                 d = c;  c &= 0377;
  362.                 crc = UPDC32(c, crc);
  363.                 if ((c = zdlread()) & ~0377)
  364.                     goto crcfoo;
  365.                 crc = UPDC32(c, crc);
  366.                 if ((c = zdlread()) & ~0377)
  367.                     goto crcfoo;
  368.                 crc = UPDC32(c, crc);
  369.                 if ((c = zdlread()) & ~0377)
  370.                     goto crcfoo;
  371.                 crc = UPDC32(c, crc);
  372.                 if ((c = zdlread()) & ~0377)
  373.                     goto crcfoo;
  374.                 crc = UPDC32(c, crc);
  375.                 if (crc != 0xDEBB20E3) {
  376.                     zperr(badcrc);
  377.                     return ERROR;
  378.                 }
  379.                 Rxcount = length - (end - buf);
  380. #ifndef DSZ
  381.                 vfile("zrdat32: %d %s", Rxcount,
  382.                  Zendnames[d-GOTCRCE&3]);
  383. #endif
  384.                 return d;
  385.             case GOTCAN:
  386.                 zperr("Sender Canceled");
  387.                 return ZCAN;
  388.             case TIMEOUT:
  389.                 zperr("TIMEOUT");
  390.                 return c;
  391.             default:
  392.                 garbitch(); return c;
  393.             }
  394.         }
  395.         *buf++ = c;
  396.         crc = UPDC32(c, crc);
  397.     }
  398.     zperr("Data subpacket too long");
  399.     return ERROR;
  400. }
  401.  
  402. garbitch()
  403. {
  404.     zperr("Garbled data subpacket");
  405. }
  406.  
  407. /*
  408.  * Read a ZMODEM header to hdr, either binary or hex.
  409.  *  eflag controls local display of non zmodem characters:
  410.  *    0:  no display
  411.  *    1:  display printing characters only
  412.  *    2:  display all non ZMODEM characters
  413.  *
  414.  *   Set Rxhlen to size of header (default 4) (valid iff good hdr)
  415.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  416.  *   Otherwise return negative on error.
  417.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  418.  */
  419. zgethdr(hdr, eflag)
  420. char *hdr;
  421. {
  422.     register int c, n, cancount;
  423.  
  424.     n = Zrwindow + Effbaud;        /* Max bytes before start of frame */
  425.     Rxframeind = Rxtype = 0;
  426.  
  427. startover:
  428.     cancount = 5;
  429. again:
  430.     /* Return immediate ERROR if ZCRCW sequence seen */
  431.     switch (c = readline(Rxtimeout)) {
  432.     case 021: case 0221:
  433.         goto again;
  434.     case RCDO:
  435.     case TIMEOUT:
  436.         goto fifi;
  437.     case CAN:
  438. gotcan:
  439.         if (--cancount <= 0) {
  440.             c = ZCAN; goto fifi;
  441.         }
  442.         switch (c = readline(1)) {
  443.         case TIMEOUT:
  444.             goto again;
  445.         case ZCRCW:
  446.             switch (readline(1)) {
  447.             case TIMEOUT:
  448.                 c = ERROR; goto fifi;
  449.             case RCDO:
  450.                 goto fifi;
  451.             default:
  452.                 goto agn2;
  453.             }
  454.         case RCDO:
  455.             goto fifi;
  456.         default:
  457.             break;
  458.         case CAN:
  459.             if (--cancount <= 0) {
  460.                 c = ZCAN; goto fifi;
  461.             }
  462.             goto again;
  463.         }
  464.     /* **** FALL THRU TO **** */
  465.     default:
  466. agn2:
  467.         if ( --n == 0) {
  468.             c = GCOUNT;  goto fifi;
  469.         }
  470.         goto startover;
  471.     case ZPAD|0200:        /* This is what we want. */
  472.         Not8bit = c;
  473.     case ZPAD:        /* This is what we want. */
  474.         break;
  475.     }
  476.     cancount = 5;
  477. splat:
  478.     switch (c = noxrd7()) {
  479.     case ZPAD:
  480.         goto splat;
  481.     case RCDO:
  482.     case TIMEOUT:
  483.         goto fifi;
  484.     default:
  485.         goto agn2;
  486.     case ZDLE:        /* This is what we want. */
  487.         break;
  488.     }
  489.  
  490.  
  491.     Rxhlen = 4;        /* Set default length */
  492.     Rxframeind = c = noxrd7();
  493.     switch (c) {
  494.     case ZVBIN32:
  495.         if ((Rxhlen = c = zdlread()) < 0)
  496.             goto fifi;
  497.         if (c > ZMAXHLEN)
  498.             goto agn2;
  499.         Crc32r = 1;  c = zrbhd32(hdr); break;
  500.     case ZBIN32:
  501.         if (Usevhdrs)
  502.             goto agn2;
  503.         Crc32r = 1;  c = zrbhd32(hdr); break;
  504.     case ZVBINR32:
  505.         if ((Rxhlen = c = zdlread()) < 0)
  506.             goto fifi;
  507.         if (c > ZMAXHLEN)
  508.             goto agn2;
  509.         Crc32r = 2;  c = zrbhd32(hdr); break;
  510.     case ZBINR32:
  511.         if (Usevhdrs)
  512.             goto agn2;
  513.         Crc32r = 2;  c = zrbhd32(hdr); break;
  514.     case RCDO:
  515.     case TIMEOUT:
  516.         goto fifi;
  517.     case ZVBIN:
  518.         if ((Rxhlen = c = zdlread()) < 0)
  519.             goto fifi;
  520.         if (c > ZMAXHLEN)
  521.             goto agn2;
  522.         Crc32r = 0;  c = zrbhdr(hdr); break;
  523.     case ZBIN:
  524.         if (Usevhdrs)
  525.             goto agn2;
  526.         Crc32r = 0;  c = zrbhdr(hdr); break;
  527.     case ZVHEX:
  528.         if ((Rxhlen = c = zgethex()) < 0)
  529.             goto fifi;
  530.         if (c > ZMAXHLEN)
  531.             goto agn2;
  532.         Crc32r = 0;  c = zrhhdr(hdr); break;
  533.     case ZHEX:
  534.         if (Usevhdrs)
  535.             goto agn2;
  536.         Crc32r = 0;  c = zrhhdr(hdr); break;
  537.     case CAN:
  538.         goto gotcan;
  539.     default:
  540.         goto agn2;
  541.     }
  542.     for (n = Rxhlen; ++n < ZMAXHLEN; )    /* Clear unused hdr bytes */
  543.         hdr[n] = 0;
  544.     Rxpos = hdr[ZP3] & 0377;
  545.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  546.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  547.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  548. fifi:
  549.     switch (c) {
  550.     case GOTCAN:
  551.         c = ZCAN;
  552.     /* **** FALL THRU TO **** */
  553.     case ZNAK:
  554.     case ZCAN:
  555.     case ERROR:
  556.     case TIMEOUT:
  557.     case RCDO:
  558.     case GCOUNT:
  559.         zperr("Got %s", frametypes[c+FTOFFSET]);
  560.     /* **** FALL THRU TO **** */
  561. #ifndef DSZ
  562.     default:
  563.         if (c >= -4 && c <= FRTYPES)
  564.             vfile("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  565.               frametypes[c+FTOFFSET], Rxpos);
  566.         else
  567.             vfile("zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
  568. #endif
  569.     }
  570.     /* Use variable length headers if we got one */
  571.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  572.         Usevhdrs = 1;
  573.     return c;
  574. }
  575.  
  576. /* Receive a binary style header (type and position) */
  577. zrbhdr(hdr)
  578. register char *hdr;
  579. {
  580.     register int c, n;
  581.     register unsigned short crc;
  582.  
  583.     if ((c = zdlread()) & ~0377)
  584.         return c;
  585.     Rxtype = c;
  586.     crc = updcrc(c, 0);
  587.  
  588.     for (n=Rxhlen; --n >= 0; ++hdr) {
  589.         if ((c = zdlread()) & ~0377)
  590.             return c;
  591.         crc = updcrc(c, crc);
  592.         *hdr = c;
  593.     }
  594.     if ((c = zdlread()) & ~0377)
  595.         return c;
  596.     crc = updcrc(c, crc);
  597.     if ((c = zdlread()) & ~0377)
  598.         return c;
  599.     crc = updcrc(c, crc);
  600.     if (crc & 0xFFFF) {
  601.         zperr(badcrc);
  602.         return ERROR;
  603.     }
  604. #ifdef ZMODEM
  605.     Protocol = ZMODEM;
  606. #endif
  607.     Zmodem = 1;
  608.     return Rxtype;
  609. }
  610.  
  611. /* Receive a binary style header (type and position) with 32 bit FCS */
  612. zrbhd32(hdr)
  613. register char *hdr;
  614. {
  615.     register int c, n;
  616.     register unsigned long crc;
  617.  
  618.     if ((c = zdlread()) & ~0377)
  619.         return c;
  620.     Rxtype = c;
  621.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  622. #ifdef DEBUGZ
  623.     vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  624. #endif
  625.  
  626.     for (n=Rxhlen; --n >= 0; ++hdr) {
  627.         if ((c = zdlread()) & ~0377)
  628.             return c;
  629.         crc = UPDC32(c, crc);
  630.         *hdr = c;
  631. #ifdef DEBUGZ
  632.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  633. #endif
  634.     }
  635.     for (n=4; --n >= 0;) {
  636.         if ((c = zdlread()) & ~0377)
  637.             return c;
  638.         crc = UPDC32(c, crc);
  639. #ifdef DEBUGZ
  640.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  641. #endif
  642.     }
  643.     if (crc != 0xDEBB20E3) {
  644.         zperr(badcrc);
  645.         return ERROR;
  646.     }
  647. #ifdef ZMODEM
  648.     Protocol = ZMODEM;
  649. #endif
  650.     Zmodem = 1;
  651.     return Rxtype;
  652. }
  653.  
  654.  
  655. /* Receive a hex style header (type and position) */
  656. zrhhdr(hdr)
  657. char *hdr;
  658. {
  659.     register int c;
  660.     register unsigned short crc;
  661.     register int n;
  662.  
  663.     if ((c = zgethex()) < 0)
  664.         return c;
  665.     Rxtype = c;
  666.     crc = updcrc(c, 0);
  667.  
  668.     for (n=Rxhlen; --n >= 0; ++hdr) {
  669.         if ((c = zgethex()) < 0)
  670.             return c;
  671.         crc = updcrc(c, crc);
  672.         *hdr = c;
  673.     }
  674.     if ((c = zgethex()) < 0)
  675.         return c;
  676.     crc = updcrc(c, crc);
  677.     if ((c = zgethex()) < 0)
  678.         return c;
  679.     crc = updcrc(c, crc);
  680.     if (crc & 0xFFFF) {
  681.         zperr(badcrc); return ERROR;
  682.     }
  683.     switch ( c = readline(2)) {
  684.     case 0215:
  685.         Not8bit = c;
  686.         /* **** FALL THRU TO **** */
  687.     case 015:
  688.          /* Throw away possible cr/lf */
  689.         switch (c = readline(2)) {
  690.         case 012:
  691.             Not8bit |= c;
  692.         }
  693.     }
  694. #ifdef ZMODEM
  695.     Protocol = ZMODEM;
  696. #endif
  697.     Zmodem = 1;
  698.     if (c < 0)
  699.         return c;
  700.     return Rxtype;
  701. }
  702.  
  703. /* Send a byte as two hex digits */
  704. zputhex(c)
  705. register int c;
  706. {
  707.     static char    digits[]    = "0123456789abcdef";
  708.  
  709. #ifdef DEBUGZ
  710.     if (Verbose>8)
  711.         vfile("zputhex: %02X", c);
  712. #endif
  713.     sendline(digits[(c&0xF0)>>4]);
  714.     sendline(digits[(c)&0xF]);
  715. }
  716.  
  717. /*
  718.  * Send character c with ZMODEM escape sequence encoding.
  719.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  720.  */
  721. zsendline(c)
  722. {
  723.  
  724.     /* Quick check for non control characters */
  725.     if (c & 0140)
  726.         xsendline(lastsent = c);
  727.     else {
  728.         switch (c &= 0377) {
  729.         case ZDLE:
  730.             xsendline(ZDLE);
  731.             xsendline (lastsent = (c ^= 0100));
  732.             break;
  733.         case 015:
  734.         case 0215:
  735.             if (!Zctlesc && (lastsent & 0177) != '@')
  736.                 goto sendit;
  737.         /* **** FALL THRU TO **** */
  738.         case 020:
  739.         case 021:
  740.         case 023:
  741.         case 0220:
  742.         case 0221:
  743.         case 0223:
  744.             xsendline(ZDLE);
  745.             c ^= 0100;
  746.     sendit:
  747.             xsendline(lastsent = c);
  748.             break;
  749.         default:
  750.             if (Zctlesc && ! (c & 0140)) {
  751.                 xsendline(ZDLE);
  752.                 c ^= 0100;
  753.             }
  754.             xsendline(lastsent = c);
  755.         }
  756.     }
  757. }
  758.  
  759. /* Decode two lower case hex digits into an 8 bit byte value */
  760. zgethex()
  761. {
  762.     register int c;
  763.  
  764.     c = zgeth1();
  765. #ifdef DEBUGZ
  766.     if (Verbose>8)
  767.         vfile("zgethex: %02X", c);
  768. #endif
  769.     return c;
  770. }
  771. zgeth1()
  772. {
  773.     register int c, n;
  774.  
  775.     if ((c = noxrd7()) < 0)
  776.         return c;
  777.     n = c - '0';
  778.     if (n > 9)
  779.         n -= ('a' - ':');
  780.     if (n & ~0xF)
  781.         return ERROR;
  782.     if ((c = noxrd7()) < 0)
  783.         return c;
  784.     c -= '0';
  785.     if (c > 9)
  786.         c -= ('a' - ':');
  787.     if (c & ~0xF)
  788.         return ERROR;
  789.     c += (n<<4);
  790.     return c;
  791. }
  792.  
  793. /*
  794.  * Read a byte, checking for ZMODEM escape encoding
  795.  *  including CAN*5 which represents a quick abort
  796.  */
  797. zdlread()
  798. {
  799.     register int c;
  800.  
  801. again:
  802.     /* Quick check for non control characters */
  803.     if ((c = readline(Rxtimeout)) & 0140)
  804.         return c;
  805.     switch (c) {
  806.     case ZDLE:
  807.         break;
  808.     case 023:
  809.     case 0223:
  810.     case 021:
  811.     case 0221:
  812.         goto again;
  813.     default:
  814.         if (Zctlesc && !(c & 0140)) {
  815.             goto again;
  816.         }
  817.         return c;
  818.     }
  819. again2:
  820.     if ((c = readline(Rxtimeout)) < 0)
  821.         return c;
  822.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  823.         return c;
  824.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  825.         return c;
  826.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  827.         return c;
  828.     switch (c) {
  829.     case CAN:
  830.         return GOTCAN;
  831.     case ZCRCE:
  832.     case ZCRCG:
  833.     case ZCRCQ:
  834.     case ZCRCW:
  835.         return (c | GOTOR);
  836.     case ZRUB0:
  837.         return 0177;
  838.     case ZRUB1:
  839.         return 0377;
  840.     case 023:
  841.     case 0223:
  842.     case 021:
  843.     case 0221:
  844.         goto again2;
  845.     default:
  846.         if (Zctlesc && ! (c & 0140)) {
  847.             goto again2;
  848.         }
  849.         if ((c & 0140) ==  0100)
  850.             return (c ^ 0100);
  851.         break;
  852.     }
  853.     if (Verbose>1)
  854.         zperr("Bad escape sequence %x", c);
  855.     return ERROR;
  856. }
  857.  
  858. /*
  859.  * Read a character from the modem line with timeout.
  860.  *  Eat parity, XON and XOFF characters.
  861.  */
  862. noxrd7()
  863. {
  864.     register int c;
  865.  
  866.     for (;;) {
  867.         if ((c = readline(Rxtimeout)) < 0)
  868.             return c;
  869.         switch (c &= 0177) {
  870.         case XON:
  871.         case XOFF:
  872.             continue;
  873.         default:
  874.             if (Zctlesc && !(c & 0140))
  875.                 continue;
  876.         case '\r':
  877.         case '\n':
  878.         case ZDLE:
  879.             return c;
  880.         }
  881.     }
  882. }
  883.  
  884. /* Store long integer pos in Txhdr */
  885. stohdr(pos)
  886. unsigned long pos;
  887. {
  888.     Txhdr[ZP0] = pos;
  889.     Txhdr[ZP1] = pos>>8;
  890.     Txhdr[ZP2] = pos>>16;
  891.     Txhdr[ZP3] = pos>>24;
  892. }
  893.  
  894. /* Recover a unsigned long integer from a header */
  895. unsigned long
  896. rclhdr(hdr)
  897. register char *hdr;
  898. {
  899.     register unsigned long l;
  900.  
  901.     l = (hdr[ZP3] & 0377);
  902.     l = (l << 8) | (hdr[ZP2] & 0377);
  903.     l = (l << 8) | (hdr[ZP1] & 0377);
  904.     l = (l << 8) | (hdr[ZP0] & 0377);
  905.     return l;
  906. }
  907.  
  908. /* End of zm.c */
  909.